use std::collections::HashMap;
use std::hash::Hash;
use std::ops::{Deref, DerefMut};
use crate::block::Block;


const DB_FILE: &str = "blockchain.db";

// 创世区块
const GENESIS_COINBASE_DATA: &str = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";


const LAST_KEY: &str = "LAST_KEY";

#[derive(Debug)]
pub struct BlockChain {
    blocks: Vec<Block>,
}

impl BlockChain {
    // 创建区块链
    pub fn new_block_chain() -> BlockChain {
        let block = Block::new_block(GENESIS_COINBASE_DATA.as_bytes().to_vec(), Vec::new());

        BlockChain {
            blocks: vec![block]
        }
    }

    pub fn add_block(&mut self, data: Vec<u8>) {
        let last_block = &self.blocks.as_slice().last().unwrap();
        let block = Block::new_block(data, last_block.hash.clone());

        self.blocks.push(block);
    }
}


#[cfg(test)]
mod test {
    use crate::blockchain;
    use crate::blockchain::BlockChain;
    use crate::utils::hex_string;

    #[test]
    fn test() {
        let mut blockchain = BlockChain::new_block_chain();

        blockchain.add_block("111".as_bytes().to_vec());
        blockchain.add_block("222".as_bytes().to_vec());
        blockchain.add_block("333".as_bytes().to_vec());

        for block in blockchain.blocks {
            println!("------------------------------------------------------------------------");

            println!("version is {}", &block.version);
            println!("prev_hash is {:?}", hex_string(&block.prev_hash));
            println!("merkle_root is {:?}", hex_string(&block.merkle_root));
            println!("time_stamp is {:?}", &block.time_stamp);
            println!("bits is {:?}", &block.bits);
            println!("nonce is {:?}", &block.nonce);
            println!("hash is {:?}", hex_string(&block.hash));
            println!("data is {:?}", String::from_utf8_lossy(&block.data));
            // println!("block is {:#?}", block);
        }
    }
}